/*LICENSE_BEGIN
 * ******************************************************************
 * Copyright 2006 by the Dainamite Robocup-Team at the
 * DAI-Labor, TU-Berlin (www.dai-labor.de)
 * 
 * Members of Dainamite are:
 * Holger Endert
 * Robert Wetzker
 * Thomas Karbe
 * Axel Heßler
 * Philippe Bütter
 * Felix Brossmann
 * 
 * Licensed under the GNU GPL (General Public License) Free Software 
 * License, Version 2. You may use this file only in compliance with 
 * the License. You may obtain a copy of the License at:
 * 
 * http://www.fsf.org/licensing/licenses/gpl.txt
 * ******************************************************************
LICENSE_END*/
package robocup.component.infotypes;

import java.util.LinkedList;

import robocup.component.speechacts.coachlanguage.AdviceMessage;
import robocup.component.speechacts.coachlanguage.DefineMessage;
import robocup.component.speechacts.coachlanguage.DeleteMessage;
import robocup.component.speechacts.coachlanguage.InfoMessage;
import robocup.component.speechacts.coachlanguage.MetaMessage;
import robocup.component.speechacts.coachlanguage.RuleMessage;
import robocup.component.speechacts.coachlanguage.TypeConstants;


/**
 * This class represents a message received from the coach. Because of the
 * complexity of the clang, there a different message types (freeform, rule,
 * advice, info, meta and delete).<br><br>
 * This info-type is used in two ways: First, it captures the messages received
 * by the players from the coach. Second, it can be translated into a string
 * with correct syntax, such that this can be sent via the server to the
 * agents, what corresponds more to an <b>action</b>.
 */
public class CoachSayInfo extends AuralInfo {

	/**
	 * The type of the message. One of INIT, FREEFORM, DEFINE, RULE, ADVICE, 
	 * INFO, META or DELETE. This defines, which of the messages that can
	 * be contained, is available in the given object.
	 */
	private TypeConstants.MESSAGETYPE messageType = TypeConstants.MESSAGETYPE.INIT;

	/**
	 * The freeform message-string.
	 */
	private String freeformMessage = "";

	/**
	 * The rule-message.
	 */
	private RuleMessage ruleMessage = null;

	/**
	 * The advice message.
	 */
	private AdviceMessage adviceMessage = null;

	/**
	 * The info message.
	 */
	private InfoMessage infoMessage = null;

	/**
	 * The meta message.
	 */
	private MetaMessage metaMessage = null;

	/**
	 * The delete message.
	 */
	private DeleteMessage deleteMessage = null;

	/**
	 * The list of define-messages.
	 */
	private LinkedList<DefineMessage> defineList = new LinkedList<DefineMessage>();

	/**
	 * Constructs an info-object for a heared message from the coach. This
	 * includes CLANG as well as freeform messages - types are defined for
	 * checking what was heared.
	 * 
	 * @param iCycle -
	 *            when was it heared
	 */
	public CoachSayInfo(int iCycle) {
		super(iCycle);
		this.infoType = Info.TYPE_AURAL_CSI;
	}

	/**
	 * @return Returns the message type of that info.
	 */
	public TypeConstants.MESSAGETYPE getMessageType() {
		return this.messageType;
	}

	/**
	 * Sets the message type for that info.
	 * @param messageType - the new message-type.
	 */
	public void setMessageType(TypeConstants.MESSAGETYPE messageType) {
		this.messageType = messageType;
	}

	/**
	 * @return Returns the rule-message.
	 */
	public RuleMessage getRuleMessage() {
		return this.ruleMessage;
	}

	/**
	 * Sets the rule-message for that info.
	 * @param ruleMessage - the new rule-message.
	 */
	public void setRuleMessage(RuleMessage ruleMessage) {
		this.ruleMessage = ruleMessage;
		this.messageType = TypeConstants.MESSAGETYPE.RULE;
	}

	/**
	 * @return Returns the freeform message string.
	 */
	public String getFreeformMessage() {
		return this.freeformMessage;
	}

	/**
	 * Sets a freeform string to this info.
	 * @param freeformMessage - the new freeform message
	 */
	public void setFreeformMessage(String freeformMessage) {
		if (freeformMessage.startsWith("\""))
			freeformMessage = freeformMessage.substring(1, freeformMessage
					.length() - 1);
		this.freeformMessage = freeformMessage;
		this.messageType = TypeConstants.MESSAGETYPE.FREEFORM;
	}

	/**
	 * Adds a define-message to this info.
	 * @param define - the new define-message.
	 */
	public void addDefine(DefineMessage define) {
		this.defineList.add(define);
		this.messageType = TypeConstants.MESSAGETYPE.DEFINE;
	}

	/**
	 * Adds a list of define-messages to that info.
	 * @param defineList - the new list.
	 */
	public void addDefineList(LinkedList<DefineMessage> defineList) {
		this.defineList.addAll(defineList);
		this.messageType = TypeConstants.MESSAGETYPE.DEFINE;
	}

	/**
	 * @return Returns the define messages.
	 */
	public LinkedList<DefineMessage> getDefineList() {
		return defineList;
	}

	/**
	 * Sets a complete define-list to that info-object.
	 * @param defineList - the new define-message list.
	 */
	public void setDefineList(LinkedList<DefineMessage> defineList) {
		this.defineList = defineList;
		this.messageType = TypeConstants.MESSAGETYPE.DEFINE;
	}

	/**
	 * @return Returns the advice-message of that info-object.
	 */
	public AdviceMessage getAdviceMessage() {
		return adviceMessage;
	}

	/**
	 * Sets a new advice-message to that info object.
	 * @param adviceMessage - the new advice-message.
	 */
	public void setAdviceMessage(AdviceMessage adviceMessage) {
		this.adviceMessage = adviceMessage;
		this.messageType = TypeConstants.MESSAGETYPE.ADVICE;
	}

	/**
	 * @return Returns the info-message of that info- object.
	 */
	public InfoMessage getInfoMessage() {
		return infoMessage;
	}

	/**
	 * Sets a new info-message to that info-object.
	 * @param infoMessage - the new info-message
	 */
	public void setInfoMessage(InfoMessage infoMessage) {
		this.infoMessage = infoMessage;
		this.messageType = TypeConstants.MESSAGETYPE.INFO;
	}

	/**
	 * @return Returns the meta-message of that info-object.
	 */
	public MetaMessage getMetaMessage() {
		return metaMessage;
	}

	/**
	 * Sets a new meta-message to that info-object.
	 * @param metaMessage - the new meta-message.
	 */
	public void setMetaMessage(MetaMessage metaMessage) {
		this.metaMessage = metaMessage;
		this.messageType = TypeConstants.MESSAGETYPE.META;
	}

	/**
	 * @return Returns the delete-message of that info-object.
	 */
	public DeleteMessage getDeleteMessage() {
		return deleteMessage;
	}

	/**
	 * Sets a new delete-message to that info-object.
	 * @param deleteMessage - the new delet-message.
	 */
	public void setDeleteMessage(DeleteMessage deleteMessage) {
		this.deleteMessage = deleteMessage;
		this.messageType = TypeConstants.MESSAGETYPE.DELETE;
	}

	/**
	 * Returns the string-representation for the given clang message. This 
	 * depends on the type of the message and on the contained messages.
	 * @return (say &lt;clang-string&gt;)
	 */
	public String toString() {
		StringBuffer buf = new StringBuffer();

		buf.append("(say ");

		switch (this.messageType) {

		case INIT:
			buf.append("empty");
			break;

		case FREEFORM:
			buf.append("(freeform \"" + this.freeformMessage + "\")");
			break;

		case RULE:
			buf.append(this.ruleMessage.toString());
			break;

		case DELETE:
			buf.append(this.deleteMessage.toString());
			break;

		case DEFINE:
			buf.append("(define");
			for (DefineMessage dm : this.defineList) {
				buf.append(" " + dm.toString());
			}
			buf.append(")");
			break;

		case META:
			buf.append(this.metaMessage.toString());
			break;

		case ADVICE:
			buf.append(this.adviceMessage.toString());
			break;

		case INFO:
			buf.append(this.infoMessage.toString());
			break;
		}

		buf.append(")");
		return buf.toString();
	}

}
